package com.example.pcl.controller.admin;

import com.example.pcl.constant.MessageConstants;
import com.example.pcl.constant.StatusCodeConstants;
import com.example.pcl.exception.ObjectException;
import com.example.pcl.pojo.dto.StudentQueryDto;
import com.example.pcl.pojo.entity.Students;
import com.example.pcl.result.Result;
import com.example.pcl.service.IStudentsService;
import com.example.pcl.utils.ExcelUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;

/**
 * <p>
 * 学生表，存储学生个人信息，包括学号，年级和学院 前端控制器
 * </p>
 *
 * @author xx
 * @since 2024-12-17
 */
@RestController("adminStudentsController")
@RequestMapping("/admin/student")
@RequiredArgsConstructor
@Slf4j
@Tag(name = "管理端学生相关接口")
public class StudentsController {

    private final IStudentsService studentService;

    /**
     * 分页查询学生数据
     *
     * @param queryDto dto
     * @return 分页后的数据
     */
    @GetMapping("/list")
    @Operation(summary = "分页查询学生列表")
    public Result<?> list(StudentQueryDto queryDto) {
        log.info("管理员分页查询学生信息：{}", queryDto);
        return Result.success(studentService.pageList(queryDto), MessageConstants.SELECT_OK);
    }

    /**
     * 添加学生
     *
     * @param student 学生实体
     * @return 提示
     */
    @PostMapping("/add")
    @Operation(summary = "添加学生")
    public Result<?> save(@RequestBody @Validated Students student) {
        log.info("管理员添加学生：{}", student);
        studentService.add(student);
        return Result.success(MessageConstants.ADD_OK);
    }

    /**
     * 修改学生信息
     *
     * @param students 学生实体
     * @return 提示
     */
    @PutMapping("/update")
    @Operation(summary = "修改学生")
    public Result<?> update(@RequestBody Students students) {
        log.info("管理员修改学生信息:{}", students);
        studentService.updateById(students);
        return Result.success(MessageConstants.OPERATION_SUCCESSFUL);
    }

    /**
     * 批量导入学生信息（Excel 文件）
     *
     * @param file 上传的 Excel 文件
     * @return 操作结果
     */
    @PostMapping("/import")
    @Operation(summary = "批量导入")
    public Result<?> importStudents(@RequestParam("file") MultipartFile file) {
        try {
            log.info("管理员批量添加学生信息:{}", file);
            List<Students> studentList = ExcelUtil.getStudentlist(file);
            studentService.addBatch(studentList);
            return Result.success(MessageConstants.OPERATION_SUCCESSFUL);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(StatusCodeConstants.INTERNAL_SERVER_ERROR, "学生信息导入失败");
        }
    }

    /**
     * 批量删除学生信息
     *
     * @param ids 学生id
     * @return 提示
     */
    @DeleteMapping("/deleteBatch")
    @Operation(summary = "批量删除学生信息")
    public Result<?> deleteBatch(@RequestParam List<Integer> ids) {
        log.info("管理员批量删除学生信息:{}", ids);
        studentService.deleteBatch(ids);
        return Result.success(MessageConstants.OPERATION_SUCCESSFUL);
    }

    /**
     * 导出学生信息
     *
     * @param response HTTP 响应
     */
    @GetMapping("/export")
    @Operation(summary = "导出学生信息")
    public void exportStudents(@NotNull HttpServletResponse response) {
        // 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment; filename=students.xlsx");

        try (ByteArrayOutputStream outputStream = studentService.exportStudents();
             ServletOutputStream servletOutputStream = response.getOutputStream()) {
            // 将数据写入响应
            servletOutputStream.write(outputStream.toByteArray());
            servletOutputStream.flush();
        } catch (IOException e) {
            throw new ObjectException("导出学生信息失败");
        }
    }

    /**
     * 查询学生详细信息
     *
     * @param id 学生id
     * @return 学生实体
     */
    @GetMapping("/detail/{id}")
    @Operation(summary = "学生详细信息")
    public Result<?> detail(@PathVariable Integer id) {
        log.info("管理员查询学生详细信息：{}", id);
        return Result.success(studentService.getById(id), MessageConstants.SELECT_OK);
    }
}